package com.atguigu.tingshu.album.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.tingshu.album.mapper.AlbumAttributeValueMapper;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.mapper.BaseCategoryViewMapper;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.common.cache.GuiGuCache;
import com.atguigu.tingshu.common.config.config.RabbitConstant;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.login.GuiGuLogin;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.AlbumAttributeValue;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.model.album.BaseCategoryView;
import com.atguigu.tingshu.query.album.AlbumInfoQuery;
import com.atguigu.tingshu.vo.album.AlbumAttributeValueVo;
import com.atguigu.tingshu.vo.album.AlbumInfoVo;
import com.atguigu.tingshu.vo.album.AlbumListVo;
import com.atguigu.tingshu.vo.album.AlbumStatVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.swagger.v3.core.util.Json;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class AlbumInfoServiceImpl extends ServiceImpl<AlbumInfoMapper, AlbumInfo> implements AlbumInfoService {

    @Autowired
    private AlbumInfoMapper albumInfoMapper;

    @Autowired
    private AlbumAttributeValueMapper albumAttributeValueMapper;

    @Autowired
    private AlbumStatMapper albumStatMapper;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RedissonClient redissonClient;


    @Override
    public void saveAlbumInfo(AlbumInfoVo albumInfoVo) {
        //存储到albumInfo
        AlbumInfo albumInfo = new AlbumInfo();
        //非空判断
        if (ObjectUtils.isEmpty(albumInfoVo)){
            return ;
        }

        BeanUtils.copyProperties(albumInfoVo,albumInfo);
        albumInfo.setUserId(AuthContextHolder.getUserId()==null?1:AuthContextHolder.getUserId());

        //	设置用户Id：可以暂时写个固定值
        albumInfo.setUserId(AuthContextHolder.getUserId() == null ? 1 : AuthContextHolder.getUserId());

        //	设置专辑审核状态为：通过
        albumInfo.setStatus(SystemConstant.ALBUM_STATUS_PASS);
        //  付费的默认前前5集免费试看
        if(!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfo.getPayType())) {
            albumInfo.setTracksForFree(5);
        }

        //新增AlbumInfo
        this.albumInfoMapper.insert(albumInfo);
        //新增到album_attribute_value
        Long albumId = albumInfo.getId();

        List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();
        if (CollectionUtils.isEmpty(albumAttributeValueVoList)){
            return;
        }

        albumAttributeValueVoList.forEach(albumAttributeValueVo -> {
            AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
            albumAttributeValue.setAlbumId(albumId);
            BeanUtils.copyProperties(albumAttributeValueVo,albumAttributeValue);
            albumAttributeValueMapper.insert(albumAttributeValue);
        });
        this.initAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_PLAY);
        this.initAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_SUBSCRIBE);
        this.initAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_BROWSE);
        this.initAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_COMMENT);

        //发送消息到mq 非私有才发
        if (albumInfoVo.getIsOpen().equals("1")){

            this.rabbitTemplate.convertAndSend(RabbitConstant.ALBUM_EXCHANGE,RabbitConstant.ALBUM_SAVE_RK,albumId);
        }


    }


    //分页查询专辑
    @Override
    public Page<AlbumListVo> findUserAlbumPage(Page<AlbumListVo> page1, AlbumInfoQuery albumInfoQuery) {
/*        Long userId = AuthContextHolder.getUserId();

        albumInfoQuery.setUserId(userId);*/
        return albumInfoMapper.findUserAlbumPage(page1,albumInfoQuery);
    }


    //根据专辑ID删除专辑
    @Override
    public void removeAlbumInfo(Long albumId) {
        //删除 专辑表
        this.removeById(albumId);

        //删除 stat统计表
        albumStatMapper.delete(new LambdaUpdateWrapper<AlbumStat>().eq(AlbumStat::getAlbumId,albumId));
        //删除 关联表 属性信息
        albumAttributeValueMapper.delete(new LambdaUpdateWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId,albumId));

        //发送到mq
        rabbitTemplate.convertAndSend(RabbitConstant.ALBUM_EXCHANGE,RabbitConstant.ALBUM_DEL_RK,albumId);

    }

    @GuiGuCache(prefix = RedisConstant.ALBUM_INFO_PREFIX,timeout =RedisConstant.ALBUM_TIMEOUT,random =RedisConstant.ALBUM_TEMPORARY_TIMEOUT
    ,lock = RedisConstant.ALBUM_LOCK_PREFIX ,bf = RedisConstant.ALBUM_BLOOM_FILTER )
    @Override
    public AlbumInfo getAlbumInfo(Long albumId) {

            //2.如果缓存没有命中 去数据库查询数据放入缓存
            //根据专辑id查询专辑详细信息 (回显)
           AlbumInfo albumInfo = this.getById(albumId);
            if (albumInfo != null){
                List<AlbumAttributeValue> albumAttributeValueList = albumAttributeValueMapper
                        .selectList(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, albumId));
                albumInfo.setAlbumAttributeValueVoList(albumAttributeValueList);
            }



            return albumInfo;

    }


    public AlbumInfo getAlbumInfo222(Long albumId) {
        String key = RedisConstant.ALBUM_INFO_PREFIX + albumId;
        //1、先查询缓存 如果缓存命中直接返回
        AlbumInfo albumInfo = (AlbumInfo)this.redisTemplate.opsForValue().get(key);
        if (albumInfo!=null){
            return albumInfo;
        }
        //使用布隆过滤器 查看专辑是否存在

        RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter(RedisConstant.ALBUM_BLOOM_FILTER);
        if (!bloomFilter.contains(key)){
            return null;
        }


        RLock lock = this.redissonClient.getLock(RedisConstant.ALBUM_LOCK_PREFIX + albumId);

        try {

            lock.lock();

            //获取到锁后 再次查询缓存  双检锁机制
            albumInfo = (AlbumInfo)this.redisTemplate.opsForValue().get(RedisConstant.ALBUM_INFO_PREFIX + albumId);
            if (albumInfo!=null){
                return albumInfo;
            }


            //2.如果缓存没有命中 去数据库查询数据放入缓存
            //根据专辑id查询专辑详细信息 (回显)
            albumInfo = this.getById(albumId);
            if (albumInfo != null){
                List<AlbumAttributeValue> albumAttributeValueList = albumAttributeValueMapper
                        .selectList(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, albumId));
                albumInfo.setAlbumAttributeValueVoList(albumAttributeValueList);
            }

            //防止雪崩设置随机存活时间
            this.redisTemplate.opsForValue().set(RedisConstant.ALBUM_INFO_PREFIX + albumId,albumInfo,RedisConstant.CACHE_TIMEOUT, TimeUnit.SECONDS);


            return albumInfo;
        }finally {
            lock.unlock();
        }

    }

    @Override
    public void updateAlbumInfo(Long albumId,AlbumInfoVo albumInfoVo) {
        //根据专辑ID更新专辑
        //三张表的数据
        //1、更新albumInfo
        AlbumInfo albumInfo = new AlbumInfo();
        albumInfo.setId(albumId);
        BeanUtils.copyProperties(albumInfoVo,albumInfo);
        this.update(albumInfo,new LambdaUpdateWrapper<AlbumInfo>().eq(AlbumInfo::getId,albumInfo.getId()));

        //album_attribute_value表 先删除 再新增
            //1.根据album删除所有行数据
        albumAttributeValueMapper.delete(new LambdaUpdateWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId,albumId));
        //2.获取集合 赋尚albumId的值 插入到表中


        List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();

        if (! (albumAttributeValueVoList!=null && albumAttributeValueVoList.size()!=0)){
         return;
        }

        albumAttributeValueVoList.forEach((albumAttributeValueVo -> {
            AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
            albumAttributeValue.setAlbumId(albumId);
            albumAttributeValue.setAttributeId(albumAttributeValueVo.getAttributeId());
            albumAttributeValue.setValueId(albumAttributeValueVo.getValueId());
            albumAttributeValueMapper.insert(albumAttributeValue);
        }));

        //发送消息到mq
        if (albumInfoVo.getIsOpen().equals("0")){
            //私有 就删除
        rabbitTemplate.convertAndSend(RabbitConstant.ALBUM_EXCHANGE,RabbitConstant.ALBUM_DEL_RK,albumId);

        }else if (albumInfoVo.getIsOpen().equals("1")){
            //公开就保存
            rabbitTemplate.convertAndSend(RabbitConstant.ALBUM_EXCHANGE,RabbitConstant.ALBUM_SAVE_RK,albumId);
        }



    }

    @Override
    @GuiGuLogin
    public List<AlbumInfo> findUserAllAlbumList() {
        //从线程中获取用户ID
        Long userId = AuthContextHolder.getUserId()==null?1: AuthContextHolder.getUserId();
        //根据用户id获取AlbumInfo

        List<AlbumInfo> list = this.list(new LambdaQueryWrapper<AlbumInfo>().eq(AlbumInfo::getUserId,userId)
                .eq(AlbumInfo::getIsDeleted,0)
                .select(AlbumInfo::getId,AlbumInfo::getAlbumTitle)
                .orderByDesc(AlbumInfo::getId));

        return list;
    }

    @Override
    public List<AlbumAttributeValue> findAlbumAttributesByAlbumId(Long albumId) {


        List<AlbumAttributeValue> albumAttributeValues = albumAttributeValueMapper.selectList(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, albumId));


        return albumAttributeValues;
    }

    @Override
    public AlbumListVo getAlbumListVoById(Long albumId) {

        return this.albumInfoMapper.getAlbumListVoById(albumId);
    }

    @Override
    public AlbumStatVo getAlbumStatByAlbumId(Long albumId) {

      return   this.albumStatMapper.getAlbumStatByAlbumId(albumId);

    }

    @Override
    public List<Long> getChangedAlbumIds(String startTime, String endTime) {

        List<AlbumStat> albumStats = this.albumStatMapper.selectList(new LambdaQueryWrapper<AlbumStat>().
                ge(AlbumStat::getUpdateTime, startTime).lt(AlbumStat::getUpdateTime, endTime).select(AlbumStat::getAlbumId));
        List<Long> albumList = albumStats.stream().distinct().map(AlbumStat::getAlbumId).collect(Collectors.toList());

        return albumList;

    }

    @Override
    public List<AlbumStatVo> getAlbumStatsByAlbumIds(List<Long> albumIds) {


    return     this.albumInfoMapper.getAlbumStatsByAlbumIds(albumIds);

    }


    private void initAlbumStat(Long albumId, String statType) {
        AlbumStat albumStat = new AlbumStat();
        albumStat.setAlbumId(albumId);
        albumStat.setStatType(statType);
        albumStat.setStatNum(0);
        albumStatMapper.insert(albumStat);
    }
}
